#ifndef LCD_H
#define LCD_H

#include "SYSTEM/sys/sys.h"

#define LCD_WR_GPIO_PORT                        GPIOD
#define LCD_WR_GPIO_PIN                         GPIO_PIN_5
#define LCD_WR_GPIO_CLK_ENABLE()                __HAL_RCC_GPIOD_CLK_ENABLE()

#define LCD_RD_GPIO_PORT                        GPIOD
#define LCD_RD_GPIO_PIN                         GPIO_PIN_4
#define LCD_RD_GPIO_CLK_ENABLE()                __HAL_RCC_GPIOD_CLK_ENABLE()

#define LCD_BL_GPIO_PORT                        GPIOB
#define LCD_BL_GPIO_PIN                         GPIO_PIN_0
#define LCD_BL_GPIO_CLK_ENABLE()                __HAL_RCC_GPIOB_CLK_ENABLE()

#define LCD_CS_GPIO_PORT                        GPIOG
#define LCD_CS_GPIO_PIN                         GPIO_PIN_12
#define LCD_CS_GPIO_CLK_ENABLE()                __HAL_RCC_GPIOG_CLK_ENABLE()

#define LCD_RS_GPIO_PORT                        GPIOG
#define LCD_RS_GPIO_PIN                         GPIO_PIN_0
#define LCD_RS_GPIO_CLK_ENABLE()                __HAL_RCC_GPIOG_CLK_ENABLE()

#define LCD_FSMC_NEX         4              /* ??FSMC_NE4?LCD_CS,???????: 1~4 */
#define LCD_FSMC_AX          10             /* ??FSMC_A10?LCD_RS,?????: 0 ~ 25 */

#define LCD_FSMC_BCRX        FSMC_Bank1->BTCR[(LCD_FSMC_NEX - 1) * 2]       /* BCR???,??LCD_FSMC_NEX???? */
#define LCD_FSMC_BTRX        FSMC_Bank1->BTCR[(LCD_FSMC_NEX - 1) * 2 + 1]   /* BTR???,??LCD_FSMC_NEX???? */
#define LCD_FSMC_BWTRX       FSMC_Bank1E->BWTR[(LCD_FSMC_NEX - 1) * 2]      /* BWTR???,??LCD_FSMC_NEX???? */

typedef struct
{
	uint16_t width;
	uint16_t height;
	uint16_t id;
	uint8_t dir;
	uint16_t wramcmd;
	uint16_t setxcmd;
	uint16_t setycmd;
} _lcd_dev;
extern _lcd_dev lcddev;
extern unsigned int g_point_color;
extern unsigned int g_back_color;

#define LCD_BL(x) do {x ? HAL_GPIO_WritePin(LCD_BL_GPIO_PORT, LCD_BL_GPIO_PIN, GPIO_PIN_SET) : \
					HAL_GPIO_WritePin(LCD_BL_GPIO_PORT, LCD_BL_GPIO_PIN, GPIO_PIN_RESET); } while(0)

typedef struct
{
	volatile uint16_t LCD_REG;
	volatile uint16_t LCD_RAM;
} LCD_TypeDef;

#define LCD_BASE (unsigned int)((0X60000000 + (0X4000000 * (LCD_FSMC_NEX - 1))) | (((1 << LCD_FSMC_AX) * 2) - 2))
#define LCD      ((LCD_TypeDef *)LCD_BASE)

#define L2R_U2D         0           /* ????,???? */
#define L2R_D2U         1           /* ????,???? */
#define R2L_U2D         2           /* ????,???? */
#define R2L_D2U         3           /* ????,???? */

#define U2D_L2R         4           /* ????,???? */
#define U2D_R2L         5           /* ????,???? */
#define D2U_L2R         6           /* ????,???? */
#define D2U_R2L         7           /* ????,???? */

#define DFT_SCAN_DIR    L2R_U2D     /* ??????? */

/* ?????? */
#define WHITE           0xFFFF      /* ?? */
#define BLACK           0x0000      /* ?? */
#define RED             0xF800      /* ?? */
#define GREEN           0x07E0      /* ?? */
#define BLUE            0x001F      /* ?? */ 
#define MAGENTA         0XF81F      /* ???/??? = BLUE + RED */
#define YELLOW          0XFFE0      /* ?? = GREEN + RED */
#define CYAN            0X07FF      /* ?? = GREEN + BLUE */  

/* ????? */
#define BROWN           0XBC40      /* ?? */
#define BRRED           0XFC07      /* ??? */
#define GRAY            0X8430      /* ?? */ 
#define DARKBLUE        0X01CF      /* ??? */
#define LIGHTBLUE       0X7D7C      /* ??? */ 
#define GRAYBLUE        0X5458      /* ??? */ 
#define LIGHTGREEN      0X841F      /* ??? */  
#define LGRAY           0XC618      /* ???(PANNEL),????? */ 
#define LGRAYBLUE       0XA651      /* ????(?????) */ 
#define LBBLUE          0X2B12      /* ????(???????) */ 

/******************************************************************************************/
/* SSD1963??????(?????) */

/* LCD????? */ 
#define SSD_HOR_RESOLUTION      800     /* LCD????? */ 
#define SSD_VER_RESOLUTION      480     /* LCD????? */ 

/* LCD?????? */ 
#define SSD_HOR_PULSE_WIDTH     1       /* ???? */ 
#define SSD_HOR_BACK_PORCH      46      /* ???? */ 
#define SSD_HOR_FRONT_PORCH     210     /* ???? */ 

#define SSD_VER_PULSE_WIDTH     1       /* ???? */ 
#define SSD_VER_BACK_PORCH      23      /* ???? */ 
#define SSD_VER_FRONT_PORCH     22      /* ???? */ 

/* ??????,???? */ 
#define SSD_HT          (SSD_HOR_RESOLUTION + SSD_HOR_BACK_PORCH + SSD_HOR_FRONT_PORCH)
#define SSD_HPS         (SSD_HOR_BACK_PORCH)
#define SSD_VT          (SSD_VER_RESOLUTION + SSD_VER_BACK_PORCH + SSD_VER_FRONT_PORCH)
#define SSD_VPS         (SSD_VER_BACK_PORCH)
   
/******************************************************************************************/
/* ???? */

void lcd_wr_data(volatile uint16_t data);            /* LCD??? */
void lcd_wr_regno(volatile uint16_t regno);          /* LCD??????/?? */
void lcd_write_reg(uint16_t regno, uint16_t data);   /* LCD?????? */
static int lcd_rd_data(void);


void lcd_init(void);                        /* ???LCD */ 
void lcd_display_on(void);                  /* ??? */ 
void lcd_display_off(void);                 /* ??? */
void lcd_scan_dir(uint8_t dir);             /* ??????? */ 
void lcd_display_dir(uint8_t dir);          /* ???????? */ 
void lcd_ssd_backlight_set(uint8_t pwm);    /* SSD1963 ???? */ 

void lcd_write_ram_prepare(void);               /* ???GRAM */ 
void lcd_set_cursor(uint16_t x, uint16_t y);    /* ???? */ 
uint32_t lcd_read_point(uint16_t x, uint16_t y);/* ??(32???,??LTDC)  */
void lcd_draw_point(uint16_t x, uint16_t y, uint32_t color);/* ??(32???,??LTDC) */

void lcd_clear(uint16_t color);     /* LCD?? */
void lcd_fill_circle(uint16_t x, uint16_t y, uint16_t r, uint16_t color);                   /* ????? */
void lcd_draw_circle(uint16_t x0, uint16_t y0, uint8_t r, uint16_t color);                  /* ?? */
void lcd_draw_hline(uint16_t x, uint16_t y, uint16_t len, uint16_t color);                  /* ???? */
void lcd_set_window(uint16_t sx, uint16_t sy, uint16_t width, uint16_t height);             /* ???? */
void lcd_fill(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey, uint32_t color);          /* ??????(32???,??LTDC) */
void lcd_color_fill(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey, uint16_t *color);   /* ?????? */
void lcd_draw_line(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color);     /* ??? */
void lcd_draw_rectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color);/* ??? */


void lcd_show_char(uint16_t x, uint16_t y, char chr, uint8_t size, uint8_t mode, uint16_t color);                       /* ?????? */
void lcd_show_num(uint16_t x, uint16_t y, uint32_t num, uint8_t len, uint8_t size, uint16_t color);                     /* ???? */
void lcd_show_xnum(uint16_t x, uint16_t y, uint32_t num, uint8_t len, uint8_t size, uint8_t mode, uint16_t color);      /* ?????? */
void lcd_show_string(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint8_t size, char *p, uint16_t color);   /* ????? */

#endif
